import json
import time
import copy
import threading
from flask import request
from flask_login import login_required, current_user
from flask_socketio import emit, join_room
from create_app import flask_obj
from application.models.model import Room,user_room,ChatHistory,User
from db_init import db
from tools.data_tools import ret_route,orm2dict
from sqlalchemy import text


socket = flask_obj.socket
ws_users = {}
send_ping_task = False
thread_lock = threading.Lock()



@socket.on('connect', namespace='/chat')
@login_required
def to_connect():
    global send_ping_task
    with thread_lock:
        if not send_ping_task:
            send_ping_task = socket.start_background_task(target=send_ping)

    ws_users[request.sid] = 0
    rooms = current_user.rooms
    room_hisory = db.session.query(user_room).filter_by(user_id=current_user.id).all()
    room_hisory = {i.room_id: i.chat_history_id for i in room_hisory}
    for room in rooms:
        last_hisory_id = room.history.order_by(text('-c_time')).first().id
        unread = room_hisory.get(room.id) < last_hisory_id
        unread_str = ""
        if unread:
            unread_str = " 您有新消息"
        emit('my_qian', {"concent": room.room_name + unread_str}, namespace='/chat')


@socket.on('reading', namespace='/chat')
@login_required
def chat_reading(msg):
    room = Room.query.filter_by(room_code=msg['room_id']).one()
    db.session.query(user_room) \
        .filter_by(room_id=room.id, user_id=current_user.id) \
        .update({'chat_history_id': msg['chat_history_id']})
    db.session.commit()


@socket.on('disconnect', namespace='/chat')
@login_required
def test_disconnect():
    print('断开链接')


@socket.on('my_hou', namespace='/chat')
@login_required
def chat_my_event(msg):
    room = Room.query.filter_by(room_code=msg['room']).first()
    chat = ChatHistory(content=msg['data'], c_time=int(time.time()), room=room.id, user_id=current_user.id)
    db.session.add(chat)
    db.session.add(chat)
    db.session.flush()
    socket.emit('my_qian', {"concent": msg['data'], 'msg_id': chat.id}, to=msg['room'], namespace='/chat')
    db.session.commit()



@socket.on('join_room', namespace='/chat')
@login_required
def chat_room_join(msg):
    join_room(msg['room'])
    socket.emit('my_qian', {"concent": f'{current_user.nikename}加入成功'}, to=msg['room'], namespace='/chat',)
    get_room_history(msg['room'])


@socket.on('create_room', namespace='/chat')
@login_required
def chat_create_room(msg):
    if not msg['room']:
        emit('my_qian', {"concent": '未知房间名字'}, namespace='/chat')
    else:
        try:
            room = Room(room_code=msg['room'], room_name=msg['room'])
            room.users.append(current_user)
            db.session.add(room)
            db.session.commit()
            emit('my_qian', {"concent": '房间创建成功'}, namespace='/chat')

        except Exception as e:
            print(e, type(e))
            emit('my_qian', {"concent": '房间已存在'}, namespace='/chat')


# 早最新 的聊天记录5条
def get_room_history(room_code):
    print(room_code)
    # 去 这个 room_code 房间里 找到最新的5条历史记录
    room = Room.query.filter_by(room_code=room_code).one()
    history = room.history.order_by(text('-c_time')).limit(5).all()

    # 发给用过户
    for i in history[::-1]:
        emit('my_qian', {"concent": i.content, 'msg_id': i.id}, namespace='/chat', )



@socket.on('pong', namespace='/chat')
@login_required
def ping_pong(msg):
    print(msg)
    ws_users[request.sid] -= 1


def send_ping():
    while 1:
        socket.sleep(5)
        keys = copy.deepcopy(list(ws_users.keys()))
        for user_ws in keys:
            ws_users[user_ws] += 1
            if ws_users[user_ws] > 3:
                ws_users.pop(user_ws)
            else:
                socket.emit('ping', {"concent": 'ping'}, to=user_ws, namespace='/chat')


def new_user():
    user_id = 0
    while 1:
        with flask_obj.app.app_context():
            socket.sleep(1)
            users = User.query.filter(User.id > user_id).all()
            db.session.commit()
            keys = copy.deepcopy(list(ws_users.keys()))
            for user_ws in keys:
                for user in users:
                    socket.emit('my_qian', {"concent": user.nikename}, to=user_ws, namespace='/chat')
                else:
                    user_id = user.id